#include <stdio.h>
#include <stdlib.h>
#include "green_types.h"
#include "green_returns.h"
#include "bytecode_definition.h"

#define PREPARE_RESULT_D	(dresult = (PDSIResult) malloc(sizeof(DSIResult)),\
							dresult->contextStackSet = contextStack,\
							dresult->generalStackPoolsSet = generalStackPoolsSet,\
							dresult->instruction = instruction)

#define OUT_OF_MAIN_CICLE	(PREPARE_RESULT_D,\
							dresult->retcode = OUT_OF_MAIN_CICLE_I,\
							dresult)

#define INVLD				(PREPARE_RESULT_D,\
							dresult->retcode = INVALID_I,\
							dresult)

#define OUT_OF_MEMORY		(PREPARE_RESULT_D,\
							dresult->retcode = OUT_OF_MEMORY_I,\
							dresult)

#define INDEX_OUT_OF_BOUND	(PREPARE_RESULT_D,\
							dresult->retcode = INDEX_OUT_OF_BOUND_I,\
							dresult)

#define STOPED				(PREPARE_RESULT_D,\
							dresult->retcode = STOPED_I,\
							dresult)

#define NO_SUCH_CONTEXT		(PREPARE_RESULT_D,\
							dresult->retcode = NO_SUCH_CONTEXT_I,\
							dresult)

#define NO_SUCH_FUNCTION	(PREPARE_RESULT_D,\
							dresult->retcode = NO_SUCH_FUNCTION_I,\
							dresult)

PGeneralStackPools generalStackPoolsSet;
PDSIResult dresult;

PGeneralStackListElement createPool_G(size_t poolsize)
{
		PGeneralStackListElement pool;
		PGeneralStackPools tmp;
		size_t i;
		pool = (PGeneralStackListElement) malloc(sizeof(GeneralStackListElement)*poolsize);
		if(pool == NULL) return NULL;
		tmp = (PGeneralStackPools) malloc(sizeof(GeneralStackPools));
		tmp->pool = pool;
		tmp->nextPool = generalStackPoolsSet;
		generalStackPoolsSet = tmp;
		poolsize--;
		for(i = 0; i < poolsize; i++)
		{
			pool[i].nextElement = pool + i + 1;
		}
		pool[i].nextElement = NULL;
		return pool;
}

PDSIResult dynamicStacksInterpreter(PContextStackListElement contextStack, unsigned char *instruction,char **constsSet,PFunctions funcsSet, size_t poolsize)
{
	PGeneralStackListElement generalStack = NULL;
	PGeneralStackListElement generalStackPoolHead = NULL;
	void *tmp;
	size_t i, j, n;
	Integer inttmp;
	generalStackPoolsSet = NULL;
	generalStackPoolHead = createPool_G(poolsize);
	if(generalStackPoolHead == NULL) return OUT_OF_MEMORY;
	while(1)
	{
		switch(*instruction)
		{
			case INVALID:return INVLD;
			case DLOAD:if(generalStackPoolHead == NULL) generalStackPoolHead = createPool_G(poolsize);
					if(generalStackPoolHead == NULL) return OUT_OF_MEMORY;
					tmp = (void*) generalStack;
					generalStack = generalStackPoolHead;
					generalStackPoolHead = generalStackPoolHead->nextElement;
					generalStack->nextElement = (PGeneralStackListElement) tmp;
					generalStack->valueD = *( (FloatingPoint*) (instruction + 1) );
					instruction += 9;
					break;
			case ILOAD:if(generalStackPoolHead == NULL) generalStackPoolHead = createPool_G(poolsize);
					if(generalStackPoolHead == NULL) return OUT_OF_MEMORY;
					tmp = (void*) generalStack;
					generalStack = generalStackPoolHead;
					generalStackPoolHead = generalStackPoolHead->nextElement;
					generalStack->nextElement = (PGeneralStackListElement) tmp;
					generalStack->valueI = *( (Integer*) (instruction + 1) );
					instruction += 9;
					break;
			case SLOAD:if(generalStackPoolHead == NULL) generalStackPoolHead = createPool_G(poolsize);
					if(generalStackPoolHead == NULL) return OUT_OF_MEMORY;
					tmp = (void*) generalStack;
					generalStack = generalStackPoolHead;
					generalStackPoolHead = generalStackPoolHead->nextElement;
					generalStack->nextElement = (PGeneralStackListElement) tmp;
					generalStack->valueS = (StringRef) constsSet[*( (StringID*) (instruction + 1) )];
					instruction += 3;
					break;
			case DLOAD0:if(generalStackPoolHead == NULL) generalStackPoolHead = createPool_G(poolsize);
					if(generalStackPoolHead == NULL) return OUT_OF_MEMORY;
					tmp = (void*) generalStack;
					generalStack = generalStackPoolHead;
					generalStackPoolHead = generalStackPoolHead->nextElement;
					generalStack->nextElement = (PGeneralStackListElement) tmp;
					generalStack->valueD = 0.0;
					instruction++;
					break;
			case ILOAD0:if(generalStackPoolHead == NULL) generalStackPoolHead = createPool_G(poolsize);
					if(generalStackPoolHead == NULL) return OUT_OF_MEMORY;
					tmp = (void*) generalStack;
					generalStack = generalStackPoolHead;
					generalStackPoolHead = generalStackPoolHead->nextElement;
					generalStack->nextElement = (PGeneralStackListElement) tmp;
					generalStack->valueI = 0;
					instruction++;
					break;
			case SLOAD0:if(generalStackPoolHead == NULL) generalStackPoolHead = createPool_G(poolsize);
					if(generalStackPoolHead == NULL) return OUT_OF_MEMORY;
					tmp = (void*) generalStack;
					generalStack = generalStackPoolHead;
					generalStackPoolHead = generalStackPoolHead->nextElement;
					generalStack->nextElement = (PGeneralStackListElement) tmp;
					generalStack->valueS = constsSet[0];
					instruction++;
					break;
			case DLOAD1:if(generalStackPoolHead == NULL) generalStackPoolHead = createPool_G(poolsize);
					if(generalStackPoolHead == NULL) return OUT_OF_MEMORY;
					tmp = (void*) generalStack;
					generalStack = generalStackPoolHead;
					generalStackPoolHead = generalStackPoolHead->nextElement;
					generalStack->nextElement = (PGeneralStackListElement) tmp;
					generalStack->valueD = 1.0;
					instruction++;
					break;
			case ILOAD1:if(generalStackPoolHead == NULL) generalStackPoolHead = createPool_G(poolsize);
					if(generalStackPoolHead == NULL) return OUT_OF_MEMORY;
					tmp = (void*) generalStack;
					generalStack = generalStackPoolHead;
					generalStackPoolHead = generalStackPoolHead->nextElement;
					generalStack->nextElement = (PGeneralStackListElement) tmp;
					generalStack->valueI = 1;
					instruction++;
					break;
			case DLOADM1:if(generalStackPoolHead == NULL) generalStackPoolHead = createPool_G(poolsize);
					if(generalStackPoolHead == NULL) return OUT_OF_MEMORY;
					tmp = (void*) generalStack;
					generalStack = generalStackPoolHead;
					generalStackPoolHead = generalStackPoolHead->nextElement;
					generalStack->nextElement = (PGeneralStackListElement) tmp;
					generalStack->valueD = -1.0;
					instruction++;
					break;
			case ILOADM1:if(generalStackPoolHead == NULL) generalStackPoolHead = createPool_G(poolsize);
					if(generalStackPoolHead == NULL) return OUT_OF_MEMORY;
					tmp = (void*) generalStack;
					generalStack = generalStackPoolHead;
					generalStackPoolHead = generalStackPoolHead->nextElement;
					generalStack->nextElement = (PGeneralStackListElement) tmp;
					generalStack->valueI = -1;
					instruction++;
					break;
			case DADD:tmp = (void*) generalStack->nextElement;
					((PGeneralStackListElement) tmp)->valueD += generalStack->valueD;
					generalStack->nextElement = generalStackPoolHead;
					generalStackPoolHead = generalStack;
					generalStack = (GeneralStackListElement*) tmp;
					instruction++;
					break;
			case IADD:tmp = (void*) generalStack->nextElement;
					((PGeneralStackListElement) tmp)->valueI += generalStack->valueI;
					generalStack->nextElement = generalStackPoolHead;
					generalStackPoolHead = generalStack;
					generalStack = (PGeneralStackListElement) tmp;
					instruction++;
					break;
			case DSUB:tmp = (void*) generalStack->nextElement;
					((PGeneralStackListElement) tmp)->valueD = generalStack->valueD - ((PGeneralStackListElement) tmp)->valueD;
					generalStack->nextElement = generalStackPoolHead;
					generalStackPoolHead = generalStack;
					generalStack = (GeneralStackListElement*) tmp;
					instruction++;
					break;
			case ISUB:tmp = (void*) generalStack->nextElement;
					((PGeneralStackListElement) tmp)->valueI = generalStack->valueI - ((PGeneralStackListElement) tmp)->valueI;
					generalStack->nextElement = generalStackPoolHead;
					generalStackPoolHead = generalStack;
					generalStack = (PGeneralStackListElement) tmp;
					instruction++;
					break;
			case DMUL:tmp = (void*) generalStack->nextElement;
					((PGeneralStackListElement) tmp)->valueD *= generalStack->valueD;
					generalStack->nextElement = generalStackPoolHead;
					generalStackPoolHead = generalStack;
					generalStack = (GeneralStackListElement*) tmp;
					instruction++;
					break;
			case IMUL:tmp = (void*) generalStack->nextElement;
					((PGeneralStackListElement) tmp)->valueI *= generalStack->valueI;
					generalStack->nextElement = generalStackPoolHead;
					generalStackPoolHead = generalStack;
					generalStack = (PGeneralStackListElement) tmp;
					instruction++;
					break;
			case DDIV:tmp = (void*) generalStack->nextElement;
					((PGeneralStackListElement) tmp)->valueD = generalStack->valueD / ((PGeneralStackListElement) tmp)->valueD;
					generalStack->nextElement = generalStackPoolHead;
					generalStackPoolHead = generalStack;
					generalStack = (PGeneralStackListElement) tmp;
					instruction++;
					break;
			case IDIV:tmp = (void*) generalStack->nextElement;
					((PGeneralStackListElement) tmp)->valueI = generalStack->valueI / ((PGeneralStackListElement) tmp)->valueI;
					generalStack->nextElement = generalStackPoolHead;
					generalStackPoolHead = generalStack;
					generalStack = (PGeneralStackListElement) tmp;
					instruction++;
					break;
			case IMOD:tmp = (void*) generalStack->nextElement;
					((PGeneralStackListElement) tmp)->valueI = generalStack->valueI % ((PGeneralStackListElement) tmp)->valueI;
					generalStack->nextElement = generalStackPoolHead;
					generalStackPoolHead = generalStack;
					generalStack = (PGeneralStackListElement) tmp;
					instruction++;
					break;
			case DNEG:generalStack->valueD = -(generalStack->valueD);
					instruction++;
					break;
			case INEG:generalStack->valueI = -(generalStack->valueI);
					instruction++;
					break;
			case IAOR:tmp = (void*) generalStack->nextElement;
					((PGeneralStackListElement) tmp)->valueI = ((PGeneralStackListElement) tmp)->valueI | generalStack->valueI;
					generalStack->nextElement = generalStackPoolHead;
					generalStackPoolHead = generalStack;
					generalStack = (PGeneralStackListElement) tmp;
					break;
			case IAAND:tmp = (void*) generalStack->nextElement;
					((PGeneralStackListElement) tmp)->valueI = ((PGeneralStackListElement) tmp)->valueI & generalStack->valueI;
					generalStack->nextElement = generalStackPoolHead;
					generalStackPoolHead = generalStack;
					generalStack = (PGeneralStackListElement) tmp;
					break;
			case IAXOR:tmp = (void*) generalStack->nextElement;
					((PGeneralStackListElement) tmp)->valueI = ((PGeneralStackListElement) tmp)->valueI ^ generalStack->valueI;
					generalStack->nextElement = generalStackPoolHead;
					generalStackPoolHead = generalStack;
					generalStack = (PGeneralStackListElement) tmp;
					break;
			case IPRINT:printf("%lld", generalStack->valueI);
					fflush(stdout);
					tmp = (void*) generalStack->nextElement;
					generalStack->nextElement = generalStackPoolHead;
					generalStackPoolHead = generalStack;
					generalStack = (PGeneralStackListElement) tmp;
					instruction++;
					break;
			case DPRINT:printf("%le", generalStack->valueD);
					fflush(stdout);
					tmp = (void*) generalStack->nextElement;
					generalStack->nextElement = generalStackPoolHead;
					generalStackPoolHead = generalStack;
					generalStack = (PGeneralStackListElement) tmp;
					instruction++;
					break;
			case SPRINT:printf("%s", (char*) generalStack->valueS);
					fflush(stdout);
					tmp = (void*) generalStack->nextElement;
					generalStack->nextElement = generalStackPoolHead;
					generalStackPoolHead = generalStack;
					generalStack = (PGeneralStackListElement) tmp;
					instruction++;
					break;
			case I2D:generalStack->valueD = generalStack->valueI;
					instruction++;
					break;
			case D2I:generalStack->valueI = generalStack->valueD;
					instruction++;
					break;
			case S2I:generalStack->valueI = atoll((char*) generalStack->valueS);
					instruction++;
					break;
			case SWAP:tmp = (void*) generalStack->nextElement;
					generalStack->nextElement = ((PGeneralStackListElement) tmp)->nextElement;
					((PGeneralStackListElement) tmp)->nextElement = generalStack;
					generalStack = (PGeneralStackListElement) tmp;
					instruction++;
					break;
			case POP:tmp = (void*) generalStack;
					generalStack = generalStack->nextElement;
					((PGeneralStackListElement) tmp)->nextElement = generalStackPoolHead;
					generalStackPoolHead = (PGeneralStackListElement) tmp;
					instruction++;
					break;
			case LOADDVAR0:if(contextStack->varAmmount < 1) return INDEX_OUT_OF_BOUND;
					if(generalStackPoolHead == NULL) generalStackPoolHead = createPool_G(poolsize);
					if(generalStackPoolHead == NULL) return OUT_OF_MEMORY;
					tmp = (void*) generalStack;
					generalStack = generalStackPoolHead;
					generalStackPoolHead = generalStackPoolHead->nextElement;
					generalStack->nextElement = (PGeneralStackListElement) tmp;
					generalStack->valueD = contextStack->variables[0].valueD;
					instruction++;
					break;
			case LOADDVAR1:if(contextStack->varAmmount < 2) return INDEX_OUT_OF_BOUND;
					if(generalStackPoolHead == NULL) generalStackPoolHead = createPool_G(poolsize);
					if(generalStackPoolHead == NULL) return OUT_OF_MEMORY;
					tmp = (void*) generalStack;
					generalStack = generalStackPoolHead;
					generalStackPoolHead = generalStackPoolHead->nextElement;
					generalStack->nextElement = (PGeneralStackListElement) tmp;
					generalStack->valueD = contextStack->variables[1].valueD;
					instruction++;
					break;
			case LOADDVAR2:if(contextStack->varAmmount < 3) return INDEX_OUT_OF_BOUND;
					if(generalStackPoolHead == NULL) generalStackPoolHead = createPool_G(poolsize);
					if(generalStackPoolHead == NULL) return OUT_OF_MEMORY;
					tmp = (void*) generalStack;
					generalStack = generalStackPoolHead;
					generalStackPoolHead = generalStackPoolHead->nextElement;
					generalStack->nextElement = (PGeneralStackListElement) tmp;
					generalStack->valueD = contextStack->variables[2].valueD;
					instruction++;
					break;
			case LOADDVAR3:if(contextStack->varAmmount < 4) return INDEX_OUT_OF_BOUND;
					if(generalStackPoolHead == NULL) generalStackPoolHead = createPool_G(poolsize);
					if(generalStackPoolHead == NULL) return OUT_OF_MEMORY;
					tmp = (void*) generalStack;
					generalStack = generalStackPoolHead;
					generalStackPoolHead = generalStackPoolHead->nextElement;
					generalStack->nextElement = (PGeneralStackListElement) tmp;
					generalStack->valueD = contextStack->variables[3].valueD;
					instruction++;
					break;
			case LOADIVAR0:if(contextStack->varAmmount < 1) return INDEX_OUT_OF_BOUND;
					if(generalStackPoolHead == NULL) generalStackPoolHead = createPool_G(poolsize);
					if(generalStackPoolHead == NULL) return OUT_OF_MEMORY;
					tmp = (void*) generalStack;
					generalStack = generalStackPoolHead;
					generalStackPoolHead = generalStackPoolHead->nextElement;
					generalStack->nextElement = (PGeneralStackListElement) tmp;
					generalStack->valueI = contextStack->variables[0].valueI;
					instruction++;
					break;
			case LOADIVAR1:if(contextStack->varAmmount < 2) return INDEX_OUT_OF_BOUND;
					if(generalStackPoolHead == NULL) generalStackPoolHead = createPool_G(poolsize);
					if(generalStackPoolHead == NULL) return OUT_OF_MEMORY;
					tmp = (void*) generalStack;
					generalStack = generalStackPoolHead;
					generalStackPoolHead = generalStackPoolHead->nextElement;
					generalStack->nextElement = (PGeneralStackListElement) tmp;
					generalStack->valueI = contextStack->variables[1].valueI;
					instruction++;
					break;
			case LOADIVAR2:if(contextStack->varAmmount < 3) return INDEX_OUT_OF_BOUND;
					if(generalStackPoolHead == NULL) generalStackPoolHead = createPool_G(poolsize);
					if(generalStackPoolHead == NULL) return OUT_OF_MEMORY;
					tmp = (void*) generalStack;
					generalStack = generalStackPoolHead;
					generalStackPoolHead = generalStackPoolHead->nextElement;
					generalStack->nextElement = (PGeneralStackListElement) tmp;
					generalStack->valueI = contextStack->variables[2].valueI;
					instruction++;
					break;
			case LOADIVAR3:if(contextStack->varAmmount < 4) return INDEX_OUT_OF_BOUND;
					if(generalStackPoolHead == NULL) generalStackPoolHead = createPool_G(poolsize);
					if(generalStackPoolHead == NULL) return OUT_OF_MEMORY;
					tmp = (void*) generalStack;
					generalStack = generalStackPoolHead;
					generalStackPoolHead = generalStackPoolHead->nextElement;
					generalStack->nextElement = (PGeneralStackListElement) tmp;
					generalStack->valueI = contextStack->variables[3].valueI;
					instruction++;
					break;
			case LOADSVAR0:if(contextStack->varAmmount < 1) return INDEX_OUT_OF_BOUND;
					if(generalStackPoolHead == NULL) generalStackPoolHead = createPool_G(poolsize);
					if(generalStackPoolHead == NULL) return OUT_OF_MEMORY;
					tmp = (void*) generalStack;
					generalStack = generalStackPoolHead;
					generalStackPoolHead = generalStackPoolHead->nextElement;
					generalStack->nextElement = (PGeneralStackListElement) tmp;
					generalStack->valueS = contextStack->variables[0].valueS;
					instruction++;
					break;
			case LOADSVAR1:if(contextStack->varAmmount < 2) return INDEX_OUT_OF_BOUND;
					if(generalStackPoolHead == NULL) generalStackPoolHead = createPool_G(poolsize);
					if(generalStackPoolHead == NULL) return OUT_OF_MEMORY;
					tmp = (void*) generalStack;
					generalStack = generalStackPoolHead;
					generalStackPoolHead = generalStackPoolHead->nextElement;
					generalStack->nextElement = (PGeneralStackListElement) tmp;
					generalStack->valueS = contextStack->variables[1].valueS;
					instruction++;
					break;
			case LOADSVAR2:if(contextStack->varAmmount < 3) return INDEX_OUT_OF_BOUND;
					if(generalStackPoolHead == NULL) generalStackPoolHead = createPool_G(poolsize);
					if(generalStackPoolHead == NULL) return OUT_OF_MEMORY;
					tmp = (void*) generalStack;
					generalStack = generalStackPoolHead;
					generalStackPoolHead = generalStackPoolHead->nextElement;
					generalStack->nextElement = (PGeneralStackListElement) tmp;
					generalStack->valueS = contextStack->variables[2].valueS;
					instruction++;
					break;
			case LOADSVAR3:if(contextStack->varAmmount < 4) return INDEX_OUT_OF_BOUND;
					if(generalStackPoolHead == NULL) generalStackPoolHead = createPool_G(poolsize);
					if(generalStackPoolHead == NULL) return OUT_OF_MEMORY;
					tmp = (void*) generalStack;
					generalStack = generalStackPoolHead;
					generalStackPoolHead = generalStackPoolHead->nextElement;
					generalStack->nextElement = (PGeneralStackListElement) tmp;
					generalStack->valueS = contextStack->variables[3].valueS;
					instruction++;
					break;
			case STOREDVAR0:if(contextStack->varAmmount < 1) return INDEX_OUT_OF_BOUND;
					contextStack->variables[0].valueD = generalStack->valueD;
					tmp = (void*) generalStack->nextElement;
					generalStack->nextElement = generalStackPoolHead;
					generalStackPoolHead = generalStack;
					generalStack = (PGeneralStackListElement) tmp;
					instruction++;
					break;
			case STOREDVAR1:if(contextStack->varAmmount < 2) return INDEX_OUT_OF_BOUND;
					contextStack->variables[1].valueD = generalStack->valueD;
					tmp = (void*) generalStack->nextElement;
					generalStack->nextElement = generalStackPoolHead;
					generalStackPoolHead = generalStack;
					generalStack = (PGeneralStackListElement) tmp;
					instruction++;
					break;
			case STOREDVAR2:if(contextStack->varAmmount < 3) return INDEX_OUT_OF_BOUND;
					contextStack->variables[2].valueD = generalStack->valueD;
					tmp = (void*) generalStack->nextElement;
					generalStack->nextElement = generalStackPoolHead;
					generalStackPoolHead = generalStack;
					generalStack = (PGeneralStackListElement) tmp;
					instruction++;
					break;
			case STOREDVAR3:if(contextStack->varAmmount < 4) return INDEX_OUT_OF_BOUND;
					contextStack->variables[3].valueD = generalStack->valueD;
					tmp = (void*) generalStack->nextElement;
					generalStack->nextElement = generalStackPoolHead;
					generalStackPoolHead = generalStack;
					generalStack = (PGeneralStackListElement) tmp;
					instruction++;
					break;
			case STOREIVAR0:if(contextStack->varAmmount < 1) return INDEX_OUT_OF_BOUND;
					contextStack->variables[0].valueI = generalStack->valueI;
					tmp = (void*) generalStack->nextElement;
					generalStack->nextElement = generalStackPoolHead;
					generalStackPoolHead = generalStack;
					generalStack = (PGeneralStackListElement) tmp;
					instruction++;
					break;
			case STOREIVAR1:if(contextStack->varAmmount < 2) return INDEX_OUT_OF_BOUND;
					contextStack->variables[1].valueI = generalStack->valueI;
					tmp = (void*) generalStack->nextElement;
					generalStack->nextElement = generalStackPoolHead;
					generalStackPoolHead = generalStack;
					generalStack = (PGeneralStackListElement) tmp;
					instruction++;
					break;
			case STOREIVAR2:if(contextStack->varAmmount < 3) return INDEX_OUT_OF_BOUND;
					contextStack->variables[2].valueI = generalStack->valueI;
					tmp = (void*) generalStack->nextElement;
					generalStack->nextElement = generalStackPoolHead;
					generalStackPoolHead = generalStack;
					generalStack = (PGeneralStackListElement) tmp;
					instruction++;
					break;
			case STOREIVAR3:if(contextStack->varAmmount < 4) return INDEX_OUT_OF_BOUND;
					contextStack->variables[3].valueI = generalStack->valueI;
					tmp = (void*) generalStack->nextElement;
					generalStack->nextElement = generalStackPoolHead;
					generalStackPoolHead = generalStack;
					generalStack = (PGeneralStackListElement) tmp;
					instruction++;
					break;
			case STORESVAR0:if(contextStack->varAmmount < 1) return INDEX_OUT_OF_BOUND;
					contextStack->variables[0].valueS = generalStack->valueS;
					tmp = (void*) generalStack->nextElement;
					generalStack->nextElement = generalStackPoolHead;
					generalStackPoolHead = generalStack;
					generalStack = (PGeneralStackListElement) tmp;
					instruction++;
					break;
			case STORESVAR1:if(contextStack->varAmmount < 2) return INDEX_OUT_OF_BOUND;
					contextStack->variables[1].valueS = generalStack->valueS;
					tmp = (void*) generalStack->nextElement;
					generalStack->nextElement = generalStackPoolHead;
					generalStackPoolHead = generalStack;
					generalStack = (PGeneralStackListElement) tmp;
					instruction++;
					break;
			case STORESVAR2:if(contextStack->varAmmount < 3) return INDEX_OUT_OF_BOUND;
					contextStack->variables[2].valueS = generalStack->valueS;
					tmp = (void*) generalStack->nextElement;
					generalStack->nextElement = generalStackPoolHead;
					generalStackPoolHead = generalStack;
					generalStack = (PGeneralStackListElement) tmp;
					instruction++;
					break;
			case STORESVAR3:if(contextStack->varAmmount < 4) return INDEX_OUT_OF_BOUND;
					contextStack->variables[3].valueS = generalStack->valueS;
					tmp = (void*) generalStack->nextElement;
					generalStack->nextElement = generalStackPoolHead;
					generalStackPoolHead = generalStack;
					generalStack = (PGeneralStackListElement) tmp;
					instruction++;
					break;
			case LOADDVAR:if(contextStack->varAmmount < *((Ammount*) (instruction + 1)) + 1) return INDEX_OUT_OF_BOUND;
					if(generalStackPoolHead == NULL) generalStackPoolHead = createPool_G(poolsize);
					if(generalStackPoolHead == NULL) return OUT_OF_MEMORY;
					tmp = (void*) generalStack;
					generalStack = generalStackPoolHead;
					generalStackPoolHead = generalStackPoolHead->nextElement;
					generalStack->nextElement = (PGeneralStackListElement) tmp;
					generalStack->valueD = contextStack->variables[*((Ammount*) (instruction + 1))].valueD;
					instruction += 3;
					break;
			case LOADIVAR:if(contextStack->varAmmount < *((Ammount*) (instruction + 1)) + 1) return INDEX_OUT_OF_BOUND;
					if(generalStackPoolHead == NULL) generalStackPoolHead = createPool_G(poolsize);
					if(generalStackPoolHead == NULL) return OUT_OF_MEMORY;
					tmp = (void*) generalStack;
					generalStack = generalStackPoolHead;
					generalStackPoolHead = generalStackPoolHead->nextElement;
					generalStack->nextElement = (PGeneralStackListElement) tmp;
					generalStack->valueI = contextStack->variables[*((Ammount*) (instruction + 1))].valueI;
					instruction += 3;
					break;
			case LOADSVAR:if(contextStack->varAmmount < *((Ammount*) (instruction + 1)) + 1) return INDEX_OUT_OF_BOUND;
					if(generalStackPoolHead == NULL) generalStackPoolHead = createPool_G(poolsize);
					if(generalStackPoolHead == NULL) return OUT_OF_MEMORY;
					tmp = (void*) generalStack;
					generalStack = generalStackPoolHead;
					generalStackPoolHead = generalStackPoolHead->nextElement;
					generalStack->nextElement = (PGeneralStackListElement) tmp;
					generalStack->valueS = contextStack->variables[*((Ammount*) (instruction + 1))].valueS;
					instruction += 3;
					break;
			case STOREDVAR:if(contextStack->varAmmount < *((Ammount*) (instruction + 1)) + 1) return INDEX_OUT_OF_BOUND;
					contextStack->variables[*((Ammount*) (instruction + 1))].valueD = generalStack->valueD;
					tmp = (void*) generalStack->nextElement;
					generalStack->nextElement = generalStackPoolHead;
					generalStackPoolHead = generalStack;
					generalStack = (PGeneralStackListElement) tmp;
					instruction += 3;
					break;
			case STOREIVAR:if(contextStack->varAmmount < *((Ammount*) (instruction + 1)) + 1) return INDEX_OUT_OF_BOUND;
					contextStack->variables[*((Ammount*) (instruction + 1))].valueI = generalStack->valueI;
					tmp = (void*) generalStack->nextElement;
					generalStack->nextElement = generalStackPoolHead;
					generalStackPoolHead = generalStack;
					generalStack = (PGeneralStackListElement) tmp;
					instruction += 3;
					break;
			case STORESVAR:if(contextStack->varAmmount < *((Ammount*) (instruction + 1)) + 1) return INDEX_OUT_OF_BOUND;
					contextStack->variables[*((Ammount*) (instruction + 1))].valueS = generalStack->valueS;
					tmp = (void*) generalStack->nextElement;
					generalStack->nextElement = generalStackPoolHead;
					generalStackPoolHead = generalStack;
					generalStack = (PGeneralStackListElement) tmp;
					instruction += 3;
					break;
			case LOADCTXDVAR://??
			case LOADCTXIVAR://??
			case LOADCTXSVAR:tmp = (void*) generalStack;
					generalStack = generalStackPoolHead;
					generalStackPoolHead = generalStackPoolHead->nextElement;
					generalStack->nextElement = (PGeneralStackListElement) tmp;
					tmp = (void*) contextStack;
					while( (tmp != NULL) || (*((FunctionID*) (instruction + 1)) != ((PContextStackListElement) tmp)->id) )
					{
						tmp = (void*) ((PContextStackListElement) tmp)->nextElement;
					}
					if(tmp == NULL) return NO_SUCH_CONTEXT;
					if(generalStackPoolHead == NULL) generalStackPoolHead = createPool_G(poolsize);
					if(generalStackPoolHead == NULL) return OUT_OF_MEMORY;
					if(((PContextStackListElement) tmp)->varAmmount < *((Ammount*) (instruction + 3)) + 1) return INDEX_OUT_OF_BOUND;
					generalStack->valueD = ((PContextStackListElement) tmp)->variables[*((Ammount*) (instruction + 3))].valueD;
					instruction += 5;
					break;
			case STORECTXDVAR://??
			case STORECTXIVAR://??
			case STORECTXSVAR:tmp = (void*) contextStack;
					while( (tmp != NULL) || (*((FunctionID*) (instruction + 1)) != ((PContextStackListElement) tmp)->id) )
					{
						tmp = (void*) ((PContextStackListElement) tmp)->nextElement;
					}
					if(tmp == NULL) return NO_SUCH_CONTEXT;
					if(((PContextStackListElement) tmp)->varAmmount < *((Ammount*) (instruction + 3)) + 1) return INDEX_OUT_OF_BOUND;
					((PContextStackListElement) tmp)->variables[*((Ammount*) (instruction + 3))].valueD = generalStack->valueD;
					tmp = (void*) generalStack->nextElement;
					generalStack->nextElement = generalStackPoolHead;
					generalStackPoolHead = generalStack;
					generalStack = (PGeneralStackListElement) tmp;
					instruction += 5;
					break;
			case DCMP:if(generalStackPoolHead == NULL) generalStackPoolHead = createPool_G(poolsize);
					if(generalStackPoolHead == NULL) return OUT_OF_MEMORY;
					if(generalStack->valueD == generalStack->nextElement->valueD)
					{
						inttmp = 0;
					}
					else if(generalStack->valueD > generalStack->nextElement->valueD)
					{
						inttmp = 1;
					}
					else
					{
						inttmp = -1;
					}
					tmp = (void*) generalStack;
					generalStack = generalStackPoolHead;
					generalStackPoolHead = generalStackPoolHead->nextElement;
					generalStack->nextElement = (PGeneralStackListElement) tmp;
					generalStack->valueI = inttmp;
					instruction++;
					break;
			case ICMP:if(generalStackPoolHead == NULL) generalStackPoolHead = createPool_G(poolsize);
					if(generalStackPoolHead == NULL) return OUT_OF_MEMORY;
					if(generalStack->valueI == generalStack->nextElement->valueI)
					{
						inttmp = 0;
					}
					else if(generalStack->valueI > generalStack->nextElement->valueI)
					{
						inttmp = 1;
					}
					else
					{
						inttmp = -1;
					}
					tmp = (void*) generalStack;
					generalStack = generalStackPoolHead;
					generalStackPoolHead = generalStackPoolHead->nextElement;
					generalStack->nextElement = (PGeneralStackListElement) tmp;
					generalStack->valueI = inttmp;
					instruction++;
					break;
			case JA:instruction += *((Offset*) (instruction + 1)) + sizeof(Offset) + 1;
					break;
			case IFICMPNE:if(generalStack->valueI != generalStack->nextElement->valueI)
					{
						instruction += *((Offset*) (instruction + 1)) + sizeof(Offset) + 1;
					}
					else
					{
						instruction += 3;
					}
					break;
			case IFICMPE:if(generalStack->valueI == generalStack->nextElement->valueI)
					{
						instruction += *((Offset*) (instruction + 1)) + sizeof(Offset) + 1;
					}
					else
					{
						instruction += 3;
					}
					break;
			case IFICMPG:if(generalStack->valueI > generalStack->nextElement->valueI)
					{
						instruction += *((Offset*) (instruction + 1)) + sizeof(Offset) + 1;
					}
					else
					{
						instruction += 3;
					}
					break;
			case IFICMPGE:if(generalStack->valueI >= generalStack->nextElement->valueI)
					{
						instruction += *((Offset*) (instruction + 1)) + sizeof(Offset) + 1;
					}
					else
					{
						instruction += 3;
					}
					break;
			case IFICMPL:if(generalStack->valueI < generalStack->nextElement->valueI)
					{
						instruction += *((Offset*) (instruction + 1)) + sizeof(Offset) + 1;
					}
					else
					{
						instruction += 3;
					}
					break;
			case IFICMPLE:if(generalStack->valueI <= generalStack->nextElement->valueI)
					{
						instruction += *((Offset*) (instruction + 1)) + sizeof(Offset) + 1;
					}
					else
					{
						instruction += 3;
					}
					break;
			case DUMP:printf("%lg\n%lld\n%llx\n",generalStack->valueD, generalStack->valueI, generalStack->valueI);
					instruction++;
					break;
			case STOP:return STOPED;
			case CALL:i = 0;
					while( funcsSet[i].id != *((FunctionID*) (instruction + 1)) )
					{
						i++;
					}
					if( funcsSet[i].id != *((FunctionID*) (instruction + 1)) )
					{
						return NO_SUCH_FUNCTION;
					}
					tmp = malloc(sizeof(ContextStackListElement));
					((PContextStackListElement) tmp)->nextElement = contextStack;
					contextStack = (PContextStackListElement) tmp;
					contextStack->id = *((FunctionID*) (instruction + 1));
					contextStack->varAmmount = funcsSet[i].varAmmount;
					contextStack->argAmmount = funcsSet[i].argAmmount;
					contextStack->variables = (PGeneralStackElement) malloc(funcsSet[i].varAmmount*sizeof(GeneralStackElement));
					for(i = 0; i < contextStack->argAmmount; i++)
					{
						contextStack->variables[i].valueI = generalStack->valueI;
						tmp = (void*) generalStack->nextElement;
						generalStack->nextElement = generalStackPoolHead;
						generalStackPoolHead = generalStack;
						generalStack = (PGeneralStackListElement) tmp;

					}
					contextStack->retPosition = instruction + 3;
					instruction = funcsSet[i].bytecode;
					break;
			case CALLNATIVE:break;//!!!!!!!
			case RETURN:if(contextStack->nextElement == NULL)
					{
						return 0;
					}
					free(contextStack->variables);
					tmp = (void*) contextStack;
					contextStack = contextStack->nextElement;
					instruction = ((PContextStackListElement) tmp)->retPosition;
					free(tmp);
					break;
			case BREAK:break;//!!!!!!!
		}
	}
	return OUT_OF_MAIN_CICLE;
}
